/**********************************************************************************************************************
 *
 * Project:    mGameEngine
 * File:       sound.cpp
 * Author:     karooolek
 * Created on: 2009-03-24
 *
 **********************************************************************************************************************/

#include "sound.h"

namespace mGameEngine
{

namespace Audio
{

Sound::Sound() :
    _data(NULL), _length(0), _sampleRate(0), _channels(0), _bps(0),
    buffer(0)
{
}

Sound::Sound(const uint8 *data,
            uint length, uint sampleRate,
            uint8 channels, uint8 bps) :
    _data(NULL), _length(0), _sampleRate(0), _channels(0), _bps(0),
    buffer(0)
{
    setData(data, length, sampleRate, channels, bps);
}

Sound::~Sound()
{
    if(_data)
    {
        delete[] _data;
    }

    if(buffer)
    {
        alDeleteBuffers(1, &buffer);
    }
}

void Sound::setData(const uint8 *data,
        uint length, uint sampleRate,
        uint8 channels, uint8 bps)
{
    // check format
    uint format = 0;
    if(channels == 1 && bps == 8)        format = AL_FORMAT_MONO8;
    else if(channels == 1 && bps == 16)    format = AL_FORMAT_MONO16;
    else if(channels == 2 && bps == 8)    format = AL_FORMAT_STEREO8;
    else if(channels == 2 && bps == 16)    format = AL_FORMAT_STEREO16;

    // unsupported format
    if(!format)
    {
        return;
    }

    // free previous data
    if(_data)
    {
        delete[] _data;
    }

    // set new data
    _length = length;
    _sampleRate = sampleRate;
    _channels = channels;
    _bps = bps;
    uint size = _length * _channels * _bps / 8;
    _data = new uint8[size];
    memcpy(_data, data, size);

    // TODO temp, this probably should be somewhere else.. where???
    // create buffer
    if(!buffer)
    {
        alGenBuffers(1, &buffer);
    }
    alBufferData(buffer, format, _data, size, _sampleRate);
}

const uint8 *Sound::getDataAt(uint sample, uint8 channel) const
{
    // sample outside sound
    if(!_data || sample >= _length)
    {
        return NULL;
    }

    // return sample data
    return _data + (sample + _channels * channel) * _bps / 8;
}

void Sound::setDataAt(const uint8 *data, uint sample, uint8 channel)
{
    // sample outside sound
    if(!_data || sample >= _length)
    {
        return;
    }

    // set sample data
    uint8 *ptr = _data + (sample + _channels * channel) * _bps / 8;
    memcpy(ptr, data, _bps / 8);
}

}
}

